﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Threading;
using System.Management;

namespace Compiled_Tests
{
    public class ProcessSpawnWatcher
    {
        private const int WAKE_UP_FREQUENCY = 200;
        Queue<IProcess> incomming;
        IList<int> monitoring;
        bool running;

        public delegate void ChildSpawned(Process proc);
        public event ChildSpawned OnSpawn;

        public ProcessSpawnWatcher(Queue<IProcess> incomming)
        {
            this.incomming = incomming;
            monitoring = new List<int>();
            running = true;

            OnSpawn += delegate(Process p) { };
        }

        public void Run()
        {
            try
            {
                while (running)
                {
                    while (incomming.Count > 0) 
                        monitoring.Add(incomming.Dequeue().Process.Id);

                    for (int i = 0; i < monitoring.Count(); i++)
                    {
                        foreach (Process child in ChildrenOf(monitoring[i]))
                        {
                            while (incomming.Count > 0) 
                                monitoring.Add(incomming.Dequeue().Process.Id);
                            if (!monitoring.Contains(child.Id))
                            {
                                OnSpawn(child);
                            }
                        }
                    }
                    Thread.Sleep(WAKE_UP_FREQUENCY);
                }
            }
            catch (Exception e)
            {
                ;
            }
        }

        private IList<Process> ChildrenOf(int pid)
        {
            ManagementObjectSearcher searcher = new ManagementObjectSearcher("Select * From Win32_Process Where ParentProcessID=" + pid);
            ManagementObjectCollection moc = searcher.Get();
            IList<Process> ret = new List<Process>();
            foreach (ManagementObject mo in moc)
            {
                try
                {
                    Process proc = Process.GetProcessById(Convert.ToInt32(mo["ProcessID"]));
                    ret.Add(proc);
                }
                catch
                {
                }
            }
            return ret;
        }

        public void Dispose()
        {
            running = false;
        }
    }
}
